#ifndef GLSCREEN_H
#define GLSCREEN_H

#include "GLEngine.h"
#include "GLGUI.h"
#include "../core/String.h"
#include "../tinyxml/tinyxml.h"


enum GLEventType
{
    EVT_Unknown = 0,
    EVT_KeyChar,
    EVT_KeyPress,
    EVT_KeyRelease,
    EVT_MouseMove,
    EVT_MousePress,
    EVT_MouseRelease,
    EVT_MouseWheel,
    EVT_Resize,
    EVT_Task,
    EVT_SoundEnd,
    EVT_GuiClick,
    EVT_Console,
    EVT_TransitionEnd
};

union GLEvent
{
	GLEventType type;
	struct
	{
	    GLEventType type;
	    int code;
	    char name;
	} key;
	struct
	{
	    GLEventType type;
	    int x;
	    int y;
	    int button;
	    int wheel;
	} mouse;
	struct
	{
	    GLEventType type;
	    int w;
	    int h;
	} resize;
	struct
	{
	    GLEventType type;
	    int id;
	    void* data;
	} task;
	struct
	{
	    GLEventType type;
	    int id;
	    int channel;
	} sound;
	struct
	{
	    GLEventType type;
	    GLGuiControl* ctl;
	    int id;
	    int param;
	} gui;
	struct
	{
	    GLEventType type;
	    const char* cmd;
	} console;
	struct
	{
	    GLEventType type;
	    int id;
	    GLEngineTransition mode;
	} transition;
};


struct GLTask
{
    GLTask() { }
    GLTask(int _id, void* _data, float _timeout) { id=_id; data=_data; timeout=_timeout; }
    int id;
    void* data;
    float timeout;
};


class GLClient
{
public:
	GLClient(GLEngine* engine);
	virtual ~GLClient();

    //virtual void onCreate() { }
    //virtual void onDestroy() { }
	virtual void onEnter() { }
    virtual void onLeave() { }
    virtual void onUpdate(float dt) { }
    virtual void onDraw() { }
	virtual void onEvent(GLEvent e) { }
    virtual void onGuiDraw(GLGuiControl* ctl) { }

	void update(float dt);
	void draw();
    void refresh();
    void receiveEvent(GLEvent e);

	inline GLEngine* getEngine() const { return m_Engine; }

	//bind engine resources
	GLTexture* 	getTexture(const char* file_name, int flags = GLTEX_REPEAT);
	GLModel* 	getModel(const char* file_name, float scale = 1.0f, int flags = 0);
    GLFont*     getFont(const char* file_name);
    void releaseTexture(GLTexture* tex);
    void releaseModel(GLModel* mdl);
    void releaseFont(GLFont* fnt);

    //audio
    inline void playSound(int snd) { m_Engine->getAudio()->playSound(snd); }
    inline void playMusic(const char* file_name) { m_Engine->getAudio()->playMusic(file_name); }
    inline void playMusic() { m_Engine->getAudio()->playMusic(); }
    inline void stopMusic() { m_Engine->getAudio()->stopMusic(); }

    //GLOBAL INPUT STATE
    MouseState mouse;
    KeyboardState keyboard;

    //GUI
    void initGui(int w, int h, GLFont* font);
    bool loadGuiXml(const char* file_name);
    void releaseGui();
    GLGuiControl* getGuiControl(int id);
    GLGuiControl* createControl(GLGuiType t, int x, int y, int w, int h, const char* text = "");
    void showGuiMenu(int x, int y, GLGuiControl* ref_ctl, const char* menu_items, int id);
    inline GLGuiControl* getGuiActiveControl() const { return m_ActiveCtl; }
    inline GLGuiControl* getGuiHoveredControl() const { return m_HoveredCtl; }
    inline GLGuiControl* getGuiDesktopControl() const { return m_Desktop; }
    inline GLGuiControl* getGuiPopupMenu() const { return m_PopupMenu; }

    inline const String& getName() const { return m_Name; }
    inline void setName(const String& s) { m_Name = s; }

    GLTask*     createTask(float timeout, int id, void* data = NULL);

private:
    void parseGuiXmlNode(TiXmlElement* elem, GLGuiControl* parent);

private:
	GLEngine* 	        m_Engine;
    String              m_Name;
	std::vector<GLTask> m_TaskList;
	//gui
    GLGuiControl*       m_Desktop;
    GLGuiControl*       m_PopupMenu;
    GLGuiControl*       m_HoveredCtl;
    GLGuiControl*       m_ClickedCtl;
    GLGuiControl*       m_ActiveCtl;
    String              m_DesktopXmlPath;
};

#endif // GLSCREEN_H
